Return to Homepage
Introduction
In the following report, I will investigate and examine which animal
is the king of attacks whether on land or in the water, by comparing the
attacks from sharks, wolves, and alligators. While this data has already
been somewhat cleaned and contains fairly simple information, this final
project aims to investigate the disparities between these three animals,
the attack locations, and the effected population. In simpler terms, who
is responsible for the most attacks? Which populations are the most
effected? Were these attacks provoked or not? These are just some of the
questions I hope to explore in this writing.
Background
This project was inspired in part by my family, my mother is from
Florida and there have been some very interesting documentaries done on
all these animals. It was also inspired by general happen stance: I
found a very nice data set on Kaggle and felt it could be an interesting
take on a seemingly dull data set. As mentioned, this data set was
found:
Fatal
Alligator Attacks
Shark
Attacks
Shark
Attacks By Hemispheres
Global
Wolf Attacks
The data set consists of various reported statistics regarding these
different attacks. Most types of attacks were not only predatory, but
unprovoked. However, some individuals were reported to provoke the
animal. Different age groups were attacked each time.
Prevention would be great, but there are not signs for those that
will and could be attacked. Alligators, sharks, and wolves have
different reasons to attack.
Data
# load all necessary libraries
library(tidyverse)
library(janitor)
library(leaflet)
library(dplyr)
library(ggplot2)
library(lubridate)
library(stringr)
library(readr)
# reading in kaggle data sets
gator <- read.csv("predators/fatal_alligator_attacks_US.csv")
g_wolves <- read.csv("predators/global_wolves.csv")
shark_1 <- read.csv("predators/Shark_attacks/attacks.csv")
shark_2 <- read.csv("predators/shark_attacks.csv")
shark_3 <- read.csv("predators/Shark_attacks/list_coor_australia.csv")
This data set was retrieved from Kaggle and has already been
somewhat cleaned for analysis. However, there are some
changes I wanted to make to the data structure, changing missing
values/empty spaces, cleaning the names, and improving characters found
throughout the data set. The following code and outputs demonstrate the
changes I’ve made to allow for smoother data analysis:
# convert column titles to snake_case
gator <-clean_names(gator)
g_wolves <-clean_names(g_wolves)
shark_1 <- clean_names(shark_1)
shark_2 <-clean_names(shark_2)
# converts all N/A chr values to actual missing values and fills in empty spaces with missing values
g_wolves$type_of_attack[is.na(g_wolves$type_of_attack) | g_wolves$type_of_attack == ""] <- "Unknown"
shark_2$type[is.na(shark_2$type) | shark_2$type == "Invalid"] <- "Unknown"
shark_1 <- shark_1[!is.na(shark_1$type), ]
shark_1_subset <- shark_1[1:6302, ]
nrow(shark_1)
## [1] 25723
## [1] 25723
# Check which rows have NA or invalid values
table(is.na(shark_1$type))
##
## FALSE
## 25723
table(shark_1$type == "Invalid")
##
## FALSE TRUE
## 25176 547
# Replace only NAs first, then Invalids
shark_1$type[is.na(shark_1$type)] <- "Unknown"
shark_1$type[shark_1$type == "Invalid"] <- "Unknown"
# converts data structure to more appropriate data types
gator <-gator %>%
mutate(location = str_extract(details, "(Miami|Florida|Georgia|Texas|Louisiana|South Carolina)"),
location = ifelse(location == "Miami", "Florida", location))
Alligator
knitr::include_graphics("media/gator.png")

Picture came from TreeHugger
Alligators are beautiful and dangerous animals. This data only shows
a small amount of deaths that have been caused by alligators. There was
no information about crocodiles (crocs), even though they do have a hand
in many deaths over the years, since invading the South. This data shows
that Florida has had the most number of attacks. I have learned over the
years, to keep an eye out whenever by water on the Southern coast. You
never know what might snap you up.

## # A tibble: 7 × 3
## # Groups: location [5]
## location sex n
## <chr> <chr> <int>
## 1 Florida female 11
## 2 Florida male 19
## 3 Georgia female 1
## 4 Louisiana male 2
## 5 South Carolina female 4
## 6 South Carolina male 1
## 7 Texas male 3

Unexpected Shark Attacks
When I first started trying to create this plot, this was the result.
Attacks happening above Greenland. I learned how wrong I was.
knitr::include_graphics("media/Unexpected_Attacks.png")

Sharks
knitr::include_graphics("media/shark.png")

Picture from britannica
If any of you have an unrealistic fear that there is something in the
water and you will get attacked, you’re not alone. Look what is
happening in Australia. Zoom out and see what is happening.
colnames(shark_3) <- c("latitude", "longitude")
center_lat <- -25.2744
center_lon <- 133.7751
zoom_level <- 5
map <- leaflet() %>%
addTiles() %>%
setView(center_lon, center_lat, zoom = zoom_level)
for (i in 1:nrow(shark_3)) {
map <- map %>% addMarkers(lng = shark_3$longitude[i], lat = shark_3$latitude[i])
}
map
knitr::include_graphics("media/Australia.png")

This is what the map looks like when zoomed out. Crazy, right?
More Attacks
shark_1$type[is.na(shark_1$type) | shark_1$type == ""] <- "Unknown"
shark_1$type[is.na(shark_1$type) | shark_1$type == "Invalid"] <- "Unknown"
shark_1_subset <- shark_1[1:6302, ]
sharks <- shark_1 %>%
group_by(country) %>%
ggplot(aes(x = type)) +
geom_bar(aes(y = ..count..)) +
geom_text(stat = 'count', aes(label = ..count..), vjust = -0.5) +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 14),
axis.text.y = element_text(size = 14),
plot.title = element_text(hjust = 0.5, size = 16),
axis.title.x = element_text(size = 16),
axis.title.y = element_text(size = 16)) +
labs(title = "Shark Attacks by Type",
x = "Type of Attack",
y = "Count of Attacks")
# Plot the chart
plot(sharks)

Does anyone have an idea what boatomg is? I think they meant boating,
but messed up on their English. It is understandable to a degree,
English is hard.
More Shark Attacks
shark_2$type[is.na(shark_2$type) | shark_2$type == "Invalid"] <- "Unknown"
shark_2 %>%
group_by(area) %>%
ggplot(aes(x = type)) +
geom_bar(aes(y = ..count..)) +
geom_text(stat = 'count', aes(label = ..count..), vjust = -0.5) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 14),
axis.text.y = element_text(size = 14),
axis.title.x = element_text(size = 16),
axis.title.y = element_text(size = 16)
) +
labs(title = "Shark Attacks by Type",
x = "Type of Attack",
y = "Count of Attacks")

top_countries <- shark_2 %>%
count(country, sort = TRUE) %>%
top_n(15, n) %>%
pull(country)
shark_2 %>%
filter(country != "",country %in% top_countries) %>%
mutate(month = month(as.Date(date, format = "%d-%B-%Y"), label = TRUE)) %>%
filter(!is.na(month)) %>%
group_by(country, month) %>%
summarise(attacks = n(), .groups = "drop") %>%
mutate(area = fct_reorder(country, attacks, .fun = sum)) %>%
ggplot(aes(x = country, y = month)) +
geom_point(aes(size = attacks, color = attacks), alpha = 0.7) +
scale_size_continuous(range = c(2, 10)) +
scale_color_gradient(low = "skyblue", high = "red") +
labs(
x = "Country",
y = "Month",
size = "Number of Attacks",
color = "Number of Attacks",
title = "Shark Attacks by Month"
) +
theme_minimal(base_size = 14) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
coord_flip()

USA
# List of all U.S. states
us_states <- c(
"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
"Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
"New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
"North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
"South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
"Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"
)
# Now filter based on U.S. states
shark_2 %>%
filter(country == "USA", area %in% us_states) %>%
mutate(month = month(as.Date(date, format = "%d-%B-%Y"), label = TRUE)) %>%
filter(!is.na(month)) %>%
group_by(area, month) %>%
summarise(attacks = n(), .groups = "drop") %>%
mutate(area = fct_reorder(area, attacks, .fun = sum, .desc = TRUE)) %>%
ggplot(aes(x = area, y = month)) +
geom_point(aes(size = attacks, color = attacks), alpha = 0.7) +
scale_size_continuous(range = c(2, 10)) +
scale_color_gradient(low = "skyblue", high = "red") +
labs(
x = "States",
y = "Month",
size = "Number of Attacks",
color = "Number of Attacks",
title = "Shark Attacks by Month in U.S.A."
) +
theme_minimal(base_size = 14) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
coord_flip()

When Comparing: USA vs. Australia
shark_2 %>%
filter(country %in% c("USA", "AUSTRALIA")) %>%
mutate(month = month(as.Date(date, format = "%d-%B-%Y"), label = TRUE)) %>%
filter(!is.na(month)) %>%
group_by(country, month) %>%
summarise(attacks = n(), .groups = "drop") %>%
ggplot(aes(x = month, y = attacks)) +
geom_point(aes(size = attacks, color = attacks), alpha = 0.7) +
scale_size_continuous(range = c(2, 10)) +
scale_color_gradient(low = "skyblue", high = "red") +
labs(
x = "Month",
y = "Number of Attacks",
size = "Number of Attacks",
color = "Number of Attacks",
title = "Monthly Shark Attacks: USA vs Australia"
) +
theme_minimal(base_size = 14) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
facet_wrap(~ country, ncol = 1)

Wolves: Before Cleaning
knitr::include_graphics("media/wolves.png")

Picture from britannica-Wolves
g_wolves$type_of_attack[is.na(g_wolves$type_of_attack) | g_wolves$type_of_attack == ""] <- "Unknown"
wolves <- g_wolves %>%
group_by(type_of_attack) %>%
ggplot(aes(x = type_of_attack)) +
geom_bar(aes(y = ..count..)) +
geom_text(stat = 'count', aes(label = ..count..), vjust = -0.5) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 14),
axis.text.y = element_text(size = 14),
axis.title.x = element_text(size = 16),
axis.title.y = element_text(size = 16)
) +
labs(x = "Types of Attacks", y = "Victim Count")
plot(wolves)

When I was looking and trying to clean the data, there were many
factors that affected it. The data was not pretty even after trying to
clean it. The attacks are even higher than data above. There was some
data that represented 15 people that were killed by wolves. All 15
people were placed on the same line. This is how it looked before really
cleaning the data.
# Read the CSV file (assuming it's saved as 'global_wolves.csv')
data <- read.csv("predators/global_wolves.csv", stringsAsFactors = FALSE)
data <- clean_names(data)
# Use a regular expression to extract the country from the 'Location' column
data$country <- sub(".*,\\s*(.*)$", "\\1", data$location)
# Extract the country from location string
data$country <- str_extract(data$location, "[^,]+$")
# Trim any leading/trailing whitespace
data$country <- trimws(data$country)
# Replace blank box with NA
data <- data %>%
mutate(type_of_attack = ifelse(type_of_attack == "", NA, type_of_attack))
data %>%
ggplot(aes(x = country, fill = type_of_attack)) +
geom_bar(position = "dodge") +
coord_flip() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Attacks and Country",
x = "Country",
y = "Count of Attacks") +
theme_minimal()+
theme(
plot.title = element_text(hjust = 0.5),
axis.text.y = element_text(size = 8))

knitr::include_graphics("media/wolves_attacks.png")

Clean-ish Wolves Data
### Attempt 2
# Load the CSV
df <- read_csv("predators/global_wolves.csv") %>%
clean_names()
# Function to split or duplicate victims
expand_victims <- function(victim_string, row_data) {
row_data <- as_tibble(row_data)
# Insert separator where gender is jammed with next name, like "maleAlex"
victim_string <- str_replace_all(victim_string, "(male|female)(?=[A-Z])", "\\1; ")
# Case 1: multiple named people
if (str_detect(victim_string, "[A-Za-z]+, \\d{1,2}, (male|female)")) {
people <- str_extract_all(victim_string, "[^,]+, \\d{1,2}, (male|female)")[[1]]
return(map_df(people, ~ mutate(row_data, victims = .x)))
}
# Case 2: vague with number
number_match <- str_match(victim_string, "(\\d+)|([Tt]wo|[Tt]hree|[Ff]our|[Ff]ive|[Ss]ix|[Ss]even|[Ee]ight)")
if (!is.na(number_match[1])) {
num <- suppressWarnings(as.numeric(number_match[1]))
if (is.na(num)) {
num <- case_when(
str_detect(number_match[1], regex("two", ignore_case = TRUE)) ~ 2,
str_detect(number_match[1], regex("three", ignore_case = TRUE)) ~ 3,
str_detect(number_match[1], regex("four", ignore_case = TRUE)) ~ 4,
str_detect(number_match[1], regex("five", ignore_case = TRUE)) ~ 5,
str_detect(number_match[1], regex("six", ignore_case = TRUE)) ~ 6,
str_detect(number_match[1], regex("seven", ignore_case = TRUE)) ~ 7,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 8,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 9,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 10,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 11,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 12,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 13,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 14,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 15,
TRUE ~ 1
)
}
return(map_df(1:num, ~ mutate(row_data, victims = "Unknown")))
}
# Default: return original row
return(row_data)
}
# Apply to each row
cleaned_df <- df %>%
rowwise() %>%
do(expand_victims(.$victims, .)) %>%
ungroup()
# First extract the country
cleaned_df <- cleaned_df %>%
mutate(country = str_extract(location, "[^,]+$") %>% str_trim())
# Then remove any trailing periods
cleaned_df <- cleaned_df %>%
mutate(country = str_remove(country, "\\.$"))
cleaned_df %>%
ggplot(aes(x = country, fill = type_of_attack)) +
geom_bar(position = "dodge") +
coord_flip() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Attacks and Country",
x = "Country",
y = "Count of Attacks") +
theme_minimal()+
theme(
plot.title = element_text(hjust = 0.5),
axis.text.y = element_text(size = 8))

knitr::include_graphics("media/Second_Attempt.png")

Cleaner Wolf Data
# Load and clean the dataset
df <- read_csv("predators/global_wolves.csv") %>%
clean_names()
# Function to expand victims and extract age & sex
expand_victims <- function(victim_string, row_data) {
row_data <- as_tibble(row_data)
victim_string <- str_replace_all(victim_string, "(male|female)(?=[A-Z])", "\\1; ")
if (str_detect(victim_string, "[A-Za-z]+,? ?\\d{1,2}, (male|female)")) {
people <- str_extract_all(victim_string, "[^,;]+,? ?\\d{1,2}, (male|female)")[[1]]
return(map_df(people, function(person) {
age <- str_extract(person, "\\d{1,2}") %>% as.numeric()
sex <- str_extract(person, "male|female")
mutate(row_data, victims = person, age = age, sex = sex)
}))
}
number_match <- str_match(victim_string, "(\\d+)|([Tt]wo|[Tt]hree|[Ff]our|[Ff]ive|[Ss]ix|[Ss]even|[Ee]ight|[Nn]ine|[Tt]en|[Ee]leven|[Tt]welve|[Tt]hirteen|[Ff]ourteen|[Ff]ifteen)")
if (!is.na(number_match[1])) {
num <- suppressWarnings(as.numeric(number_match[1]))
if (is.na(num)) {
num <- case_when(
str_detect(number_match[1], regex("two", ignore_case = TRUE)) ~ 2,
str_detect(number_match[1], regex("three", ignore_case = TRUE)) ~ 3,
str_detect(number_match[1], regex("four", ignore_case = TRUE)) ~ 4,
str_detect(number_match[1], regex("five", ignore_case = TRUE)) ~ 5,
str_detect(number_match[1], regex("six", ignore_case = TRUE)) ~ 6,
str_detect(number_match[1], regex("seven", ignore_case = TRUE)) ~ 7,
str_detect(number_match[1], regex("eight", ignore_case = TRUE)) ~ 8,
str_detect(number_match[1], regex("nine", ignore_case = TRUE)) ~ 9,
str_detect(number_match[1], regex("ten", ignore_case = TRUE)) ~ 10,
str_detect(number_match[1], regex("eleven", ignore_case = TRUE)) ~ 11,
str_detect(number_match[1], regex("twelve", ignore_case = TRUE)) ~ 12,
str_detect(number_match[1], regex("thirteen", ignore_case = TRUE)) ~ 13,
str_detect(number_match[1], regex("fourteen", ignore_case = TRUE)) ~ 14,
str_detect(number_match[1], regex("fifteen", ignore_case = TRUE)) ~ 15,
TRUE ~ 1
)
}
return(map_df(1:num, ~ mutate(row_data, victims = "Unknown", age = NA, sex = NA)))
}
sex <- str_extract(victim_string, "male|female")
age <- str_extract(victim_string, "\\d{1,2}") %>% as.numeric()
return(mutate(row_data, victims = victim_string, age = age, sex = sex))
}
# Expand victims into individual rows
cleaned_df <- df %>%
rowwise() %>%
do(expand_victims(.$victims, .)) %>%
ungroup()
# Clean country info from 'location' column
cleaned_df <- cleaned_df %>%
mutate(
country = str_extract(location, "[^,]+$") %>% str_trim(),
country = str_remove(country, "\\.")
) %>%
filter(!is.na(country) & country != "")
# Get top 15 countries by number of attacks
top_countries <- cleaned_df %>%
count(country, sort = TRUE) %>%
slice_head(n = 15) %>%
pull(country)
# Filter to just those countries
filtered_df <- cleaned_df %>%
filter(country %in% top_countries)
filtered_df <- filtered_df %>%
filter(!is.na(type_of_attack) & type_of_attack != "")
# Plot
filtered_df %>%
ggplot(aes(x = fct_infreq(country), fill = type_of_attack)) +
geom_bar(position = "dodge") +
coord_flip() +
theme_minimal() +
labs(
title = "Top 15 Countries with Wolf Attacks",
x = "Country",
y = "Number of Attacks",
fill = "Attack Type"
) +
theme(
plot.title = element_text(hjust = 0.5, size = 18),
axis.text.x = element_text(size = 12),
axis.text.y = element_text(size = 12),
axis.title.x = element_text(size = 14),
axis.title.y = element_text(size = 14),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)

After cleaning the data, you can see, Russia and France both have
many attacks.
Who is King?
# 1. Summarize the number of attacks from each cleaned dataset
# Alligator
gator_attacks <- gator %>%
filter(!is.na(date)) %>%
nrow()
# Shark - Using shark_1 since it has most rows and was pre-cleaned
shark_attacks <- shark_1 %>%
filter(!is.na(type), type != "Unknown") %>%
nrow()
# Wolves - Using cleaned_df from wolf data
wolf_attacks <- cleaned_df %>%
filter(!is.na(type_of_attack), type_of_attack != "") %>%
nrow()
# 2. Create a comparison data frame
attack_king_df <- tibble(
predator = c("Shark", "Alligator", "Wolf"),
total_attacks = c(shark_attacks, gator_attacks, wolf_attacks)
)
# 3. Plot it
attack_king_df %>%
ggplot(aes(x = reorder(predator, total_attacks), y = total_attacks, fill = predator)) +
geom_col(width = 0.6) +
geom_text(aes(label = total_attacks), vjust = -0.5, size = 4) +
labs(
title = "The King of Attacks",
x = "Predator",
y = "Documented Attacks"
) +
scale_fill_manual(values = c("Shark" = "#FF3C38", "Alligator" = "#0C9463", "Wolf" = "#4C4C6D")) +
theme_minimal(base_size = 16) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 20),
legend.position = "none"
)

Long Live King Jaws
The King of attacks is the shark. The data shows that sharks have the
most attacks. Look at the map of Australia again, every marker is where
a shark attack has occurred. Also, another reason why the shark data is
king is due to a lack and missing data from both the wolves and gators.
If there was data for Nile Crocs, there might be some competition.
knitr::include_graphics("media/shark.png")

Picture from britannica
Tour Guide Tips
When visiting Florida or Australia, watch your feet and surroundings.
In Florida, pretty much everything wants to eat you from bugs to
Alligators/Crocs, snakes, sharks, etc. It is a dangerous and wonderful
place, as long as, you are careful. Besides, all the things that are
wanting to eat you…make for a tasty meal on your dinner plate in the
end. I want to return to Florida to get some croc/gator meat. Shark is
not bad, it is just a fishy, chewy meat.
Australia has a larger variety of dangers, a lot of shark attacks,
poisonous snakes, jellyfish, crocs, and other dangers. PBS has been my
guide to Australia.
Main Points:
1- Do not underestimate a predator by thinking they are slow
2- Watch your surroundings
3- Be careful when going near any water source
4- Don’t provoke the wildlife
5- Do not feed the wildlife
6- Do not get close to the wildlife (Potential Death Risk)
7- If you are stung by a jellyfish rinse the area with water, do not
urinate on it
8- If you are bit, (depending on what bit you and where you are bit)
if you have a weapon, fight back.
With crocs and gators: eyes, nose, or throat are recommended to stab
at. If it is a snake or a insect get help, as soon as possible.
If you are bit by a gator/croc, shark, snakes, ants, spiders, or any
sort of wildlife get help ASAP, you can potentially die from a bacterial
infection or rabies.
Some snakes in Florida (cottonmouth snake) are just nasty and have a
bad bacteria in their mouth that will cause gangrene.
Honorable Mentions
1- Golden Labs
2- Birds
3- Jellyfish
4- Etc.
LS0tCnRpdGxlOiAiRmluYWwgUHJvamVjdDogV2hvIGlzIEtpbmcgb2YgQXR0YWNrcz8iCmF1dGhvcjogIk1lYWdoYW4gQmFycmV0dCIKZGF0ZTogIjIwMjUtMDQtMDgiCm91dHB1dDogCiAgICBodG1sX2RvY3VtZW50OgogICAgICAgIHRoZW1lOiBwYXBlcgogICAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgICB0b2M6IHRydWUKICAgICAgICB0b2NfZmxvYXQ6CiAgICAgICAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgZGZfcHJpbnQ6IGthYmxlCiAgICAgICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICAgICAgbW9kZTogc2VsZmNvbnRhaW5lZAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgY2FjaGUgPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgpbUmV0dXJuIHRvIEhvbWVwYWdlXSguLi9pbmRleC5odG1sKQoKIyAqKkludHJvZHVjdGlvbioqCkluIHRoZSBmb2xsb3dpbmcgcmVwb3J0LCBJIHdpbGwgaW52ZXN0aWdhdGUgYW5kIGV4YW1pbmUgd2hpY2ggYW5pbWFsIGlzIHRoZSBraW5nIG9mIGF0dGFja3Mgd2hldGhlciBvbiBsYW5kIG9yIGluIHRoZSB3YXRlciwgYnkgY29tcGFyaW5nIHRoZSBhdHRhY2tzIGZyb20gc2hhcmtzLCB3b2x2ZXMsIGFuZCBhbGxpZ2F0b3JzLiBXaGlsZSB0aGlzIGRhdGEgaGFzIGFscmVhZHkgYmVlbiBzb21ld2hhdCBjbGVhbmVkIGFuZCBjb250YWlucyBmYWlybHkgc2ltcGxlIGluZm9ybWF0aW9uLCB0aGlzIGZpbmFsIHByb2plY3QgYWltcyB0byBpbnZlc3RpZ2F0ZSB0aGUgZGlzcGFyaXRpZXMgYmV0d2VlbiB0aGVzZSB0aHJlZSBhbmltYWxzLCB0aGUgYXR0YWNrIGxvY2F0aW9ucywgYW5kIHRoZSBlZmZlY3RlZCBwb3B1bGF0aW9uLiBJbiBzaW1wbGVyIHRlcm1zLCB3aG8gaXMgcmVzcG9uc2libGUgZm9yIHRoZSBtb3N0IGF0dGFja3M/IFdoaWNoIHBvcHVsYXRpb25zIGFyZSB0aGUgbW9zdCBlZmZlY3RlZD8gV2VyZSB0aGVzZSBhdHRhY2tzIHByb3Zva2VkIG9yIG5vdD8gVGhlc2UgYXJlIGp1c3Qgc29tZSBvZiB0aGUgcXVlc3Rpb25zIEkgaG9wZSB0byBleHBsb3JlIGluIHRoaXMgd3JpdGluZy4gCgojICoqQmFja2dyb3VuZCoqClRoaXMgcHJvamVjdCB3YXMgaW5zcGlyZWQgaW4gcGFydCBieSBteSBmYW1pbHksIG15IG1vdGhlciBpcyBmcm9tIEZsb3JpZGEgYW5kIHRoZXJlIGhhdmUgYmVlbiBzb21lIHZlcnkgaW50ZXJlc3RpbmcgZG9jdW1lbnRhcmllcyBkb25lIG9uIGFsbCB0aGVzZSBhbmltYWxzLiBJdCB3YXMgYWxzbyBpbnNwaXJlZCBieSBnZW5lcmFsIGhhcHBlbiBzdGFuY2U6IEkgZm91bmQgYSB2ZXJ5IG5pY2UgZGF0YSBzZXQgb24gS2FnZ2xlIGFuZCBmZWx0IGl0IGNvdWxkIGJlIGFuIGludGVyZXN0aW5nIHRha2Ugb24gYSBzZWVtaW5nbHkgZHVsbCBkYXRhIHNldC4gQXMgbWVudGlvbmVkLCB0aGlzIGRhdGEgc2V0IHdhcyBmb3VuZDogCgpbRmF0YWwgQWxsaWdhdG9yIEF0dGFja3NdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZGFuZWxhL2ZhdGFsLWFsbGlnYXRvci1hdHRhY2tzLXVzP3Jlc291cmNlPWRvd25sb2FkJnNlbGVjdD1mYXRhbF9hbGxpZ2F0b3JfYXR0YWNrc19VUy5jc3YpCgpbU2hhcmsgQXR0YWNrc10oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9mZWxpcGVlc2Mvc2hhcmstYXR0YWNrLWRhdGFzZXQ/cGhhc2U9RmluaXNoU1NPUmVnaXN0cmF0aW9uJnJldHVyblVybD0lMkZkYXRhc2V0cyUyRmZlbGlwZWVzYyUyRnNoYXJrLWF0dGFjay1kYXRhc2V0JTJGdmVyc2lvbnMlMkYxJTNGcmVzb3VyY2UlM0Rkb3dubG9hZCZTU09SZWdpc3RyYXRpb25Ub2tlbj1DZkRKOFBIU0NMOWs5czFIdUoyY1JGQkZodWhncHhOMGdfQVRESVR6Xy1jWFZHLW41LVM4UGNBblpkZ0RYSGJuN3VkMGlhVllMZVlXa1luRlRZNk5jNEpGdDFueVdBWnNUdWhSOHZTUHYzb2s1VFA0QXRSUks5LUl6R0RxU3paS1VHeE1heUtLNU5La2RXZ2V3VVZZUE1GMWFKbDRwaFBCNE9id1hsMkFLNzY5OENFMjMweXNzOWtnYkFWS2NaQUNCZzAwRm1TUFBrVHNZR2hsV3U0ejNWcmV6dlpEWG9MbjJlWWF5STA3ODRKREFuYWExTDVLVnN2cHpvbEdUazlUOGhuN3VEdFgyOXJ3TlJhUVd5MTlCc1YwS1o3VGNmRGZGcFl2UkQ4clNNcnE0eUV1bDctQ1JhMkwxUjVxV3Z4RU9ZTWxHSS1WRk44N3NnYWJPUHJnX0NKNmpjSmFWbzBDY3NRJkRpc3BsYXlOYW1lPU1lYWdoYW4rQmFycmV0dCkKCltTaGFyayBBdHRhY2tzIEJ5IEhlbWlzcGhlcmVzXShodHRwczovL3d3dy5rYWdnbGUuY29tL2NvZGUvaWNlY3JlYW00L3NoYXJrLWF0dGFja3MtYnktaGVtaXNwaGVyZXMvbm90ZWJvb2spIAoKW0dsb2JhbCBXb2xmIEF0dGFja3NdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZGFuZWxhL2dsb2JhbC13b2xmLWF0dGFja3M/c2VsZWN0PWdsb2JhbF93b2x2ZXMuY3N2KSAKClRoZSBkYXRhIHNldCBjb25zaXN0cyBvZiB2YXJpb3VzIHJlcG9ydGVkIHN0YXRpc3RpY3MgcmVnYXJkaW5nIHRoZXNlIGRpZmZlcmVudCBhdHRhY2tzLiBNb3N0IHR5cGVzIG9mIGF0dGFja3Mgd2VyZSBub3Qgb25seSBwcmVkYXRvcnksIGJ1dCB1bnByb3Zva2VkLiBIb3dldmVyLCBzb21lIGluZGl2aWR1YWxzIHdlcmUgcmVwb3J0ZWQgdG8gcHJvdm9rZSB0aGUgYW5pbWFsLiBEaWZmZXJlbnQgYWdlIGdyb3VwcyB3ZXJlIGF0dGFja2VkIGVhY2ggdGltZS4gCgpQcmV2ZW50aW9uIHdvdWxkIGJlIGdyZWF0LCBidXQgdGhlcmUgYXJlIG5vdCBzaWducyBmb3IgdGhvc2UgdGhhdCB3aWxsIGFuZCBjb3VsZCBiZSBhdHRhY2tlZC4gQWxsaWdhdG9ycywgc2hhcmtzLCBhbmQgd29sdmVzIGhhdmUgZGlmZmVyZW50IHJlYXNvbnMgdG8gYXR0YWNrLiAgCgojICoqRGF0YSoqCmBgYHtyLCBlY2hvID0gVFJVRX0KIyBsb2FkIGFsbCBuZWNlc3NhcnkgbGlicmFyaWVzIApsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkcikKCiMgcmVhZGluZyBpbiBrYWdnbGUgZGF0YSBzZXRzIApnYXRvciA8LSByZWFkLmNzdigicHJlZGF0b3JzL2ZhdGFsX2FsbGlnYXRvcl9hdHRhY2tzX1VTLmNzdiIpCgpnX3dvbHZlcyA8LSByZWFkLmNzdigicHJlZGF0b3JzL2dsb2JhbF93b2x2ZXMuY3N2IikKCnNoYXJrXzEgPC0gcmVhZC5jc3YoInByZWRhdG9ycy9TaGFya19hdHRhY2tzL2F0dGFja3MuY3N2IikKCnNoYXJrXzIgPC0gcmVhZC5jc3YoInByZWRhdG9ycy9zaGFya19hdHRhY2tzLmNzdiIpCgpzaGFya18zIDwtIHJlYWQuY3N2KCJwcmVkYXRvcnMvU2hhcmtfYXR0YWNrcy9saXN0X2Nvb3JfYXVzdHJhbGlhLmNzdiIpCgpgYGAKVGhpcyBkYXRhIHNldCB3YXMgcmV0cmlldmVkIGZyb20gS2FnZ2xlIGFuZCBoYXMgYWxyZWFkeSBiZWVuICoqc29tZXdoYXQqKiBjbGVhbmVkIGZvciBhbmFseXNpcy4gSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUgY2hhbmdlcyBJIHdhbnRlZCB0byBtYWtlIHRvIHRoZSBkYXRhIHN0cnVjdHVyZSwgY2hhbmdpbmcgbWlzc2luZyB2YWx1ZXMvZW1wdHkgc3BhY2VzLCBjbGVhbmluZyB0aGUgbmFtZXMsIGFuZCBpbXByb3ZpbmcgY2hhcmFjdGVycyBmb3VuZCB0aHJvdWdob3V0IHRoZSBkYXRhIHNldC4gVGhlIGZvbGxvd2luZyBjb2RlIGFuZCBvdXRwdXRzIGRlbW9uc3RyYXRlIHRoZSBjaGFuZ2VzIEkndmUgbWFkZSB0byBhbGxvdyBmb3Igc21vb3RoZXIgZGF0YSBhbmFseXNpczogCgpgYGB7ciwgZWNobz1UUlVFfQoKIyBjb252ZXJ0IGNvbHVtbiB0aXRsZXMgdG8gc25ha2VfY2FzZSAKCmdhdG9yIDwtY2xlYW5fbmFtZXMoZ2F0b3IpCgpnX3dvbHZlcyA8LWNsZWFuX25hbWVzKGdfd29sdmVzKQoKc2hhcmtfMSA8LSBjbGVhbl9uYW1lcyhzaGFya18xKQoKc2hhcmtfMiA8LWNsZWFuX25hbWVzKHNoYXJrXzIpCmBgYAoKYGBge3IgZXZhbCA9IFRSVUV9CiMgY29udmVydHMgYWxsIE4vQSBjaHIgdmFsdWVzIHRvIGFjdHVhbCBtaXNzaW5nIHZhbHVlcyBhbmQgZmlsbHMgaW4gZW1wdHkgc3BhY2VzIHdpdGggbWlzc2luZyB2YWx1ZXMgCgpnX3dvbHZlcyR0eXBlX29mX2F0dGFja1tpcy5uYShnX3dvbHZlcyR0eXBlX29mX2F0dGFjaykgfCBnX3dvbHZlcyR0eXBlX29mX2F0dGFjayA9PSAiIl0gPC0gIlVua25vd24iCgpzaGFya18yJHR5cGVbaXMubmEoc2hhcmtfMiR0eXBlKSB8IHNoYXJrXzIkdHlwZSA9PSAiSW52YWxpZCJdIDwtICJVbmtub3duIgoKc2hhcmtfMSA8LSBzaGFya18xWyFpcy5uYShzaGFya18xJHR5cGUpLCBdIApzaGFya18xX3N1YnNldCA8LSBzaGFya18xWzE6NjMwMiwgXQpucm93KHNoYXJrXzEpCmxlbmd0aChzaGFya18xJHR5cGUpCgojIENoZWNrIHdoaWNoIHJvd3MgaGF2ZSBOQSBvciBpbnZhbGlkIHZhbHVlcwp0YWJsZShpcy5uYShzaGFya18xJHR5cGUpKSAgCnRhYmxlKHNoYXJrXzEkdHlwZSA9PSAiSW52YWxpZCIpICAKCiMgUmVwbGFjZSBvbmx5IE5BcyBmaXJzdCwgdGhlbiBJbnZhbGlkcwpzaGFya18xJHR5cGVbaXMubmEoc2hhcmtfMSR0eXBlKV0gPC0gIlVua25vd24iCnNoYXJrXzEkdHlwZVtzaGFya18xJHR5cGUgPT0gIkludmFsaWQiXSA8LSAiVW5rbm93biIKCgojIGNvbnZlcnRzIGRhdGEgc3RydWN0dXJlIHRvIG1vcmUgYXBwcm9wcmlhdGUgZGF0YSB0eXBlcwpnYXRvciA8LWdhdG9yICU+JSAKICBtdXRhdGUobG9jYXRpb24gPSBzdHJfZXh0cmFjdChkZXRhaWxzLCAiKE1pYW1pfEZsb3JpZGF8R2VvcmdpYXxUZXhhc3xMb3Vpc2lhbmF8U291dGggQ2Fyb2xpbmEpIiksCiAgICAgICAgIGxvY2F0aW9uID0gaWZlbHNlKGxvY2F0aW9uID09ICJNaWFtaSIsICJGbG9yaWRhIiwgbG9jYXRpb24pKQoKYGBgCgojICoqQWxsaWdhdG9yKioKCgpgYGB7ciwgb3V0LndpZHRoPSI3MCUiLCBvdXQuaGVpZ2h0PSI3MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibWVkaWEvZ2F0b3IucG5nIikKYGBgCgpQaWN0dXJlIGNhbWUgZnJvbSBbVHJlZUh1Z2dlcl0oaHR0cHM6Ly93d3cudHJlZWh1Z2dlci5jb20vYWxsaWdhdG9yLWZhY3RzLTUxMTkyMTQpCgpBbGxpZ2F0b3JzIGFyZSBiZWF1dGlmdWwgYW5kIGRhbmdlcm91cyBhbmltYWxzLiBUaGlzIGRhdGEgb25seSBzaG93cyBhIHNtYWxsIGFtb3VudCBvZiBkZWF0aHMgdGhhdCBoYXZlIGJlZW4gY2F1c2VkIGJ5IGFsbGlnYXRvcnMuIFRoZXJlIHdhcyBubyBpbmZvcm1hdGlvbiBhYm91dCBjcm9jb2RpbGVzIChjcm9jcyksIGV2ZW4gdGhvdWdoIHRoZXkgZG8gaGF2ZSBhIGhhbmQgaW4gbWFueSBkZWF0aHMgb3ZlciB0aGUgeWVhcnMsIHNpbmNlIGludmFkaW5nIHRoZSBTb3V0aC4gVGhpcyBkYXRhIHNob3dzIHRoYXQgRmxvcmlkYSBoYXMgaGFkIHRoZSBtb3N0IG51bWJlciBvZiBhdHRhY2tzLiBJIGhhdmUgbGVhcm5lZCBvdmVyIHRoZSB5ZWFycywgdG8ga2VlcCBhbiBleWUgb3V0IHdoZW5ldmVyIGJ5IHdhdGVyIG9uIHRoZSBTb3V0aGVybiBjb2FzdC4gWW91IG5ldmVyIGtub3cgd2hhdCBtaWdodCBzbmFwIHlvdSB1cC4gCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpnYXRvciAlPiUKICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoZGF0ZSwgZm9ybWF0ID0gIiVCICVkLCAlWSIpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShkYXRlKSkgJT4lIAogIGZpbHRlcihhZ2UgIT0gIj8iKSAlPiUKICBtdXRhdGUoYWdlID0gYXMubnVtZXJpYyhhZ2UpKSAlPiUKICBmaWx0ZXIoYWdlID49IDIgJiBhZ2UgPD0gODEpICU+JQogIG11dGF0ZSh5ZWFyID0gYXMuaW50ZWdlcihmb3JtYXQoZGF0ZSwgIiVZIikpKSAlPiUgIAogIGFycmFuZ2UoYWdlKSAlPiUKICBncm91cF9ieShsb2NhdGlvbikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKHllYXIpLCB5ID0gYWdlLCBjb2xvciA9IGxvY2F0aW9uKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCBzaXplID0gMTQpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIikKICApICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSAiQWdlIiwgdGl0bGUgPSAiR2F0b3IgQXR0YWNrczogQWdlcyB2cy4gTG9jYXRpb24iKQoKYGBgCgoKYGBge3IsIGVjaG89RkFMU0V9CmRlYXRocyA8LWdhdG9yICU+JQogIGZpbHRlcihsb2NhdGlvbiAhPSAiPyIpICU+JSAgCiAgZmlsdGVyKHNleCAhPSAiPyIpICU+JSAgICAgICAKICBncm91cF9ieShsb2NhdGlvbiwgc2V4KSAlPiUKICB0YWxseSgpCgpwcmludChkZWF0aHMpCgp2aWN0aW1zX2J5X3N0YXRlIDwtIGRlYXRocyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9jYXRpb24sIHkgPSBuLCBmaWxsID0gc2V4KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsgIAogIGdlb21fdGV4dChhZXMobGFiZWwgPSBuKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDMpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpCiAgKSArIAogIGxhYnMoCiAgICB0aXRsZSA9ICJBbGxpZ2F0b3IgQXR0YWNrcyBieSBTdGF0ZSIsCiAgICB4ID0gIlN0YXRlIiwgeSA9ICJOdW1iZXIgb2YgVmljdGltcyIsIGZpbGwgPSAiU2V4IgogICkKCgoKdmljdGltc19ieV9zdGF0ZQpgYGAKCiMgKipVbmV4cGVjdGVkIFNoYXJrIEF0dGFja3MqKgpXaGVuIEkgZmlyc3Qgc3RhcnRlZCB0cnlpbmcgdG8gY3JlYXRlIHRoaXMgcGxvdCwgdGhpcyB3YXMgdGhlIHJlc3VsdC4gQXR0YWNrcyBoYXBwZW5pbmcgYWJvdmUgR3JlZW5sYW5kLiBJIGxlYXJuZWQgaG93IHdyb25nIEkgd2FzLiAKYGBge3IsIG91dC53aWR0aD0iNzAlIiwgb3V0LmhlaWdodD0iNzAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm1lZGlhL1VuZXhwZWN0ZWRfQXR0YWNrcy5wbmciKQpgYGAKCiMgKipTaGFya3MqKgoKCmBgYHtyLCBvdXQud2lkdGg9IjcwJSIsIG91dC5oZWlnaHQ9IjcwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtZWRpYS9zaGFyay5wbmciKQpgYGAKClBpY3R1cmUgZnJvbSBbYnJpdGFubmljYV0oaHR0cHM6Ly93d3cuYnJpdGFubmljYS5jb20vYW5pbWFsL3NoYXJrKQoKCgpJZiBhbnkgb2YgeW91IGhhdmUgYW4gdW5yZWFsaXN0aWMgZmVhciB0aGF0IHRoZXJlIGlzIHNvbWV0aGluZyBpbiB0aGUgd2F0ZXIgYW5kIHlvdSB3aWxsIGdldCBhdHRhY2tlZCwgeW91J3JlIG5vdCBhbG9uZS4gTG9vayB3aGF0IGlzIGhhcHBlbmluZyBpbiBBdXN0cmFsaWEuIFpvb20gb3V0IGFuZCBzZWUgd2hhdCBpcyBoYXBwZW5pbmcuCgpgYGB7ciwgZWNobyA9IFRSVUV9Cgpjb2xuYW1lcyhzaGFya18zKSA8LSBjKCJsYXRpdHVkZSIsICJsb25naXR1ZGUiKQpjZW50ZXJfbGF0IDwtIC0yNS4yNzQ0CmNlbnRlcl9sb24gPC0gMTMzLjc3NTEKem9vbV9sZXZlbCA8LSA1ICAKCm1hcCA8LSBsZWFmbGV0KCkgJT4lCiAgYWRkVGlsZXMoKSAlPiUgIAogIHNldFZpZXcoY2VudGVyX2xvbiwgY2VudGVyX2xhdCwgem9vbSA9IHpvb21fbGV2ZWwpCgpmb3IgKGkgaW4gMTpucm93KHNoYXJrXzMpKSB7CiAgbWFwIDwtIG1hcCAlPiUgYWRkTWFya2VycyhsbmcgPSBzaGFya18zJGxvbmdpdHVkZVtpXSwgbGF0ID0gc2hhcmtfMyRsYXRpdHVkZVtpXSkKfQoKbWFwCgpgYGAKCgpgYGB7ciwgb3V0LndpZHRoPSIxMDAlIiwgb3V0LmhlaWdodD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtZWRpYS9BdXN0cmFsaWEucG5nIikKYGBgCgoKVGhpcyBpcyB3aGF0IHRoZSBtYXAgbG9va3MgbGlrZSB3aGVuIHpvb21lZCBvdXQuIENyYXp5LCByaWdodD8KCgojICAqKk1vcmUgQXR0YWNrcyoqCmBgYHtyLCBlY2hvPVRSVUV9CgpzaGFya18xJHR5cGVbaXMubmEoc2hhcmtfMSR0eXBlKSB8IHNoYXJrXzEkdHlwZSA9PSAiIl0gPC0gIlVua25vd24iCnNoYXJrXzEkdHlwZVtpcy5uYShzaGFya18xJHR5cGUpIHwgc2hhcmtfMSR0eXBlID09ICJJbnZhbGlkIl0gPC0gIlVua25vd24iCnNoYXJrXzFfc3Vic2V0IDwtIHNoYXJrXzFbMTo2MzAyLCBdCgpzaGFya3MgPC0gc2hhcmtfMSAlPiUgCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHR5cGUpKSArCiAgZ2VvbV9iYXIoYWVzKHkgPSAuLmNvdW50Li4pKSArIAogIGdlb21fdGV4dChzdGF0ID0gJ2NvdW50JywgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgdmp1c3QgPSAtMC41KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTQpLCAgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwgIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNiksICAKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwgIAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArIAogIGxhYnModGl0bGUgPSAiU2hhcmsgQXR0YWNrcyBieSBUeXBlIiwgCiAgICAgICB4ID0gIlR5cGUgb2YgQXR0YWNrIiwgCiAgICAgICB5ID0gIkNvdW50IG9mIEF0dGFja3MiKQoKIyBQbG90IHRoZSBjaGFydApwbG90KHNoYXJrcykKCmBgYAoKCkRvZXMgYW55b25lIGhhdmUgYW4gaWRlYSB3aGF0IGJvYXRvbWcgaXM/IEkgdGhpbmsgdGhleSBtZWFudCBib2F0aW5nLCBidXQgbWVzc2VkIHVwIG9uIHRoZWlyIEVuZ2xpc2guIEl0IGlzIHVuZGVyc3RhbmRhYmxlIHRvIGEgZGVncmVlLCBFbmdsaXNoIGlzIGhhcmQuIAoKCiMgKipNb3JlIFNoYXJrIEF0dGFja3MqKgpgYGB7ciwgZWNobyA9IFRSVUV9CgpzaGFya18yJHR5cGVbaXMubmEoc2hhcmtfMiR0eXBlKSB8IHNoYXJrXzIkdHlwZSA9PSAiSW52YWxpZCJdIDwtICJVbmtub3duIgoKc2hhcmtfMiAlPiUgCiAgZ3JvdXBfYnkoYXJlYSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHR5cGUpKSArCiAgZ2VvbV9iYXIoYWVzKHkgPSAuLmNvdW50Li4pKSArIAogIGdlb21fdGV4dChzdGF0ID0gJ2NvdW50JywgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgdmp1c3QgPSAtMC41KSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxNCksICAKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksICAKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLCAgCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSAgIAogICkgKyAKICBsYWJzKHRpdGxlID0gIlNoYXJrIEF0dGFja3MgYnkgVHlwZSIsIAogICAgICAgeCA9ICJUeXBlIG9mIEF0dGFjayIsIAogICAgICAgeSA9ICJDb3VudCBvZiBBdHRhY2tzIikKCmBgYApgYGB7ciwgZWNobz1UUlVFfQoKdG9wX2NvdW50cmllcyA8LSBzaGFya18yICU+JQogIGNvdW50KGNvdW50cnksIHNvcnQgPSBUUlVFKSAlPiUKICB0b3BfbigxNSwgbikgJT4lCiAgcHVsbChjb3VudHJ5KQoKCnNoYXJrXzIgJT4lCiAgZmlsdGVyKGNvdW50cnkgIT0gIiIsY291bnRyeSAlaW4lIHRvcF9jb3VudHJpZXMpICU+JQogIG11dGF0ZShtb250aCA9IG1vbnRoKGFzLkRhdGUoZGF0ZSwgZm9ybWF0ID0gIiVkLSVCLSVZIiksIGxhYmVsID0gVFJVRSkpICU+JQogIGZpbHRlcighaXMubmEobW9udGgpKSAlPiUKICBncm91cF9ieShjb3VudHJ5LCBtb250aCkgJT4lCiAgc3VtbWFyaXNlKGF0dGFja3MgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIG11dGF0ZShhcmVhID0gZmN0X3Jlb3JkZXIoY291bnRyeSwgYXR0YWNrcywgLmZ1biA9IHN1bSkpICU+JQogIGdncGxvdChhZXMoeCA9IGNvdW50cnksIHkgPSBtb250aCkpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gYXR0YWNrcywgY29sb3IgPSBhdHRhY2tzKSwgYWxwaGEgPSAwLjcpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDEwKSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJza3libHVlIiwgaGlnaCA9ICJyZWQiKSArCiAgbGFicygKICAgIHggPSAiQ291bnRyeSIsCiAgICB5ID0gIk1vbnRoIiwKICAgIHNpemUgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgY29sb3IgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgdGl0bGUgPSAiU2hhcmsgQXR0YWNrcyBieSBNb250aCIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgKwogIGNvb3JkX2ZsaXAoKQoKYGBgCgoKIyAqKlVTQSoqCgpgYGB7ciwgZWNobz1UUlVFfQoKIyBMaXN0IG9mIGFsbCBVLlMuIHN0YXRlcwp1c19zdGF0ZXMgPC0gYygKICAiQWxhYmFtYSIsICJBbGFza2EiLCAiQXJpem9uYSIsICJBcmthbnNhcyIsICJDYWxpZm9ybmlhIiwgIkNvbG9yYWRvIiwgIkNvbm5lY3RpY3V0IiwgCiAgIkRlbGF3YXJlIiwgIkZsb3JpZGEiLCAiR2VvcmdpYSIsICJIYXdhaWkiLCAiSWRhaG8iLCAiSWxsaW5vaXMiLCAiSW5kaWFuYSIsICJJb3dhIiwgCiAgIkthbnNhcyIsICJLZW50dWNreSIsICJMb3Vpc2lhbmEiLCAiTWFpbmUiLCAiTWFyeWxhbmQiLCAiTWFzc2FjaHVzZXR0cyIsICJNaWNoaWdhbiIsIAogICJNaW5uZXNvdGEiLCAiTWlzc2lzc2lwcGkiLCAiTWlzc291cmkiLCAiTW9udGFuYSIsICJOZWJyYXNrYSIsICJOZXZhZGEiLCAKICAiTmV3IEhhbXBzaGlyZSIsICJOZXcgSmVyc2V5IiwgIk5ldyBNZXhpY28iLCAiTmV3IFlvcmsiLCAiTm9ydGggQ2Fyb2xpbmEiLCAKICAiTm9ydGggRGFrb3RhIiwgIk9oaW8iLCAiT2tsYWhvbWEiLCAiT3JlZ29uIiwgIlBlbm5zeWx2YW5pYSIsICJSaG9kZSBJc2xhbmQiLCAKICAiU291dGggQ2Fyb2xpbmEiLCAiU291dGggRGFrb3RhIiwgIlRlbm5lc3NlZSIsICJUZXhhcyIsICJVdGFoIiwgIlZlcm1vbnQiLCAKICAiVmlyZ2luaWEiLCAiV2FzaGluZ3RvbiIsICJXZXN0IFZpcmdpbmlhIiwgIldpc2NvbnNpbiIsICJXeW9taW5nIgopCgojIE5vdyBmaWx0ZXIgYmFzZWQgb24gVS5TLiBzdGF0ZXMKc2hhcmtfMiAlPiUKICBmaWx0ZXIoY291bnRyeSA9PSAiVVNBIiwgYXJlYSAlaW4lIHVzX3N0YXRlcykgJT4lCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoYXMuRGF0ZShkYXRlLCBmb3JtYXQgPSAiJWQtJUItJVkiKSwgbGFiZWwgPSBUUlVFKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShtb250aCkpICU+JQogIGdyb3VwX2J5KGFyZWEsIG1vbnRoKSAlPiUKICBzdW1tYXJpc2UoYXR0YWNrcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgbXV0YXRlKGFyZWEgPSBmY3RfcmVvcmRlcihhcmVhLCBhdHRhY2tzLCAuZnVuID0gc3VtLCAuZGVzYyA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhcmVhLCB5ID0gbW9udGgpKSArCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGF0dGFja3MsIGNvbG9yID0gYXR0YWNrcyksIGFscGhhID0gMC43KSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCAxMCkpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3cgPSAic2t5Ymx1ZSIsIGhpZ2ggPSAicmVkIikgKwogIGxhYnMoCiAgICB4ID0gIlN0YXRlcyIsCiAgICB5ID0gIk1vbnRoIiwKICAgIHNpemUgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgY29sb3IgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgdGl0bGUgPSAiU2hhcmsgQXR0YWNrcyBieSBNb250aCBpbiBVLlMuQS4iCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpICsKICBjb29yZF9mbGlwKCkKCmBgYAoKCiMgKipXaGVuIENvbXBhcmluZzogVVNBIHZzLiBBdXN0cmFsaWEqKgoKYGBge3IsIGVjaG89VFJVRX0Kc2hhcmtfMiAlPiUKICBmaWx0ZXIoY291bnRyeSAlaW4lIGMoIlVTQSIsICJBVVNUUkFMSUEiKSkgJT4lCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoYXMuRGF0ZShkYXRlLCBmb3JtYXQgPSAiJWQtJUItJVkiKSwgbGFiZWwgPSBUUlVFKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShtb250aCkpICU+JQogIGdyb3VwX2J5KGNvdW50cnksIG1vbnRoKSAlPiUKICBzdW1tYXJpc2UoYXR0YWNrcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbW9udGgsIHkgPSBhdHRhY2tzKSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBhdHRhY2tzLCBjb2xvciA9IGF0dGFja3MpLCBhbHBoYSA9IDAuNykgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgMTApKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gInNreWJsdWUiLCBoaWdoID0gInJlZCIpICsKICBsYWJzKAogICAgeCA9ICJNb250aCIsCiAgICB5ID0gIk51bWJlciBvZiBBdHRhY2tzIiwKICAgIHNpemUgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgY29sb3IgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgdGl0bGUgPSAiTW9udGhseSBTaGFyayBBdHRhY2tzOiBVU0EgdnMgQXVzdHJhbGlhIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgZmFjZXRfd3JhcCh+IGNvdW50cnksIG5jb2wgPSAxKQoKYGBgCgojICAqKldvbHZlczogQmVmb3JlIENsZWFuaW5nKioKCgpgYGB7ciwgb3V0LndpZHRoPSI3MCUiLCBvdXQuaGVpZ2h0PSI3MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibWVkaWEvd29sdmVzLnBuZyIpCmBgYAoKClBpY3R1cmUgZnJvbSBbYnJpdGFubmljYS1Xb2x2ZXNdKGh0dHBzOi8vd3d3LmJyaXRhbm5pY2EuY29tL2FuaW1hbC93b2xmKQoKCmBgYHtyLCBlY2hvPVRSVUV9Cmdfd29sdmVzJHR5cGVfb2ZfYXR0YWNrW2lzLm5hKGdfd29sdmVzJHR5cGVfb2ZfYXR0YWNrKSB8IGdfd29sdmVzJHR5cGVfb2ZfYXR0YWNrID09ICIiXSA8LSAiVW5rbm93biIKCndvbHZlcyA8LSBnX3dvbHZlcyAlPiUgCiAgZ3JvdXBfYnkodHlwZV9vZl9hdHRhY2spICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB0eXBlX29mX2F0dGFjaykpICArCiAgZ2VvbV9iYXIoYWVzKHkgPSAuLmNvdW50Li4pKSArIAogIGdlb21fdGV4dChzdGF0ID0gJ2NvdW50JywgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgdmp1c3QgPSAtMC41KSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSAxNCksICAKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksIAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksICAKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpICAKICApICsKICBsYWJzKHggPSAiVHlwZXMgb2YgQXR0YWNrcyIsIHkgPSAiVmljdGltIENvdW50IikKCnBsb3Qod29sdmVzKQoKYGBgCgoKV2hlbiBJIHdhcyBsb29raW5nIGFuZCB0cnlpbmcgdG8gY2xlYW4gdGhlIGRhdGEsIHRoZXJlIHdlcmUgbWFueSBmYWN0b3JzIHRoYXQgYWZmZWN0ZWQgaXQuIFRoZSBkYXRhIHdhcyBub3QgcHJldHR5IGV2ZW4gYWZ0ZXIgdHJ5aW5nIHRvIGNsZWFuIGl0LiBUaGUgYXR0YWNrcyBhcmUgZXZlbiBoaWdoZXIgdGhhbiBkYXRhIGFib3ZlLiBUaGVyZSB3YXMgc29tZSBkYXRhIHRoYXQgcmVwcmVzZW50ZWQgMTUgcGVvcGxlIHRoYXQgd2VyZSBraWxsZWQgYnkgd29sdmVzLiBBbGwgMTUgcGVvcGxlIHdlcmUgcGxhY2VkIG9uIHRoZSBzYW1lIGxpbmUuIFRoaXMgaXMgaG93IGl0IGxvb2tlZCBiZWZvcmUgcmVhbGx5IGNsZWFuaW5nIHRoZSBkYXRhLiAKCmBgYHtyLCBlY2hvPVRSVUV9CiMgUmVhZCB0aGUgQ1NWIGZpbGUgKGFzc3VtaW5nIGl0J3Mgc2F2ZWQgYXMgJ2dsb2JhbF93b2x2ZXMuY3N2JykKZGF0YSA8LSByZWFkLmNzdigicHJlZGF0b3JzL2dsb2JhbF93b2x2ZXMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKZGF0YSA8LSBjbGVhbl9uYW1lcyhkYXRhKQoKIyBVc2UgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZXh0cmFjdCB0aGUgY291bnRyeSBmcm9tIHRoZSAnTG9jYXRpb24nIGNvbHVtbgpkYXRhJGNvdW50cnkgPC0gc3ViKCIuKixcXHMqKC4qKSQiLCAiXFwxIiwgZGF0YSRsb2NhdGlvbikKCiMgRXh0cmFjdCB0aGUgY291bnRyeSBmcm9tIGxvY2F0aW9uIHN0cmluZwpkYXRhJGNvdW50cnkgPC0gc3RyX2V4dHJhY3QoZGF0YSRsb2NhdGlvbiwgIlteLF0rJCIpCgojIFRyaW0gYW55IGxlYWRpbmcvdHJhaWxpbmcgd2hpdGVzcGFjZQpkYXRhJGNvdW50cnkgPC0gdHJpbXdzKGRhdGEkY291bnRyeSkKCiMgUmVwbGFjZSBibGFuayBib3ggd2l0aCBOQQpkYXRhIDwtIGRhdGEgJT4lCiAgbXV0YXRlKHR5cGVfb2ZfYXR0YWNrID0gaWZlbHNlKHR5cGVfb2ZfYXR0YWNrID09ICIiLCBOQSwgdHlwZV9vZl9hdHRhY2spKQoKZGF0YSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY291bnRyeSwgZmlsbCA9IHR5cGVfb2ZfYXR0YWNrKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwogIGNvb3JkX2ZsaXAoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsgIAogIGxhYnModGl0bGUgPSAiQXR0YWNrcyBhbmQgQ291bnRyeSIsCiAgICAgICB4ID0gIkNvdW50cnkiLAogICAgICAgeSA9ICJDb3VudCBvZiBBdHRhY2tzIikgKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSAgCmBgYAoKYGBge3IsIG91dC53aWR0aD0iMTAwJSIsIG91dC5oZWlnaHQ9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibWVkaWEvd29sdmVzX2F0dGFja3MucG5nIikKYGBgCgoKIyAqKkNsZWFuLWlzaCBXb2x2ZXMgRGF0YSoqCgpgYGB7ciwgZWNobz1UUlVFfQojIyMgQXR0ZW1wdCAyCiMgTG9hZCB0aGUgQ1NWCmRmIDwtIHJlYWRfY3N2KCJwcmVkYXRvcnMvZ2xvYmFsX3dvbHZlcy5jc3YiKSAlPiUgCiAgY2xlYW5fbmFtZXMoKQoKIyBGdW5jdGlvbiB0byBzcGxpdCBvciBkdXBsaWNhdGUgdmljdGltcwpleHBhbmRfdmljdGltcyA8LSBmdW5jdGlvbih2aWN0aW1fc3RyaW5nLCByb3dfZGF0YSkgewogIHJvd19kYXRhIDwtIGFzX3RpYmJsZShyb3dfZGF0YSkgIAogIAogICMgSW5zZXJ0IHNlcGFyYXRvciB3aGVyZSBnZW5kZXIgaXMgamFtbWVkIHdpdGggbmV4dCBuYW1lLCBsaWtlICJtYWxlQWxleCIKICB2aWN0aW1fc3RyaW5nIDwtIHN0cl9yZXBsYWNlX2FsbCh2aWN0aW1fc3RyaW5nLCAiKG1hbGV8ZmVtYWxlKSg/PVtBLVpdKSIsICJcXDE7ICIpCiAgCiAgIyBDYXNlIDE6IG11bHRpcGxlIG5hbWVkIHBlb3BsZQogIGlmIChzdHJfZGV0ZWN0KHZpY3RpbV9zdHJpbmcsICJbQS1aYS16XSssIFxcZHsxLDJ9LCAobWFsZXxmZW1hbGUpIikpIHsKICAgIHBlb3BsZSA8LSBzdHJfZXh0cmFjdF9hbGwodmljdGltX3N0cmluZywgIlteLF0rLCBcXGR7MSwyfSwgKG1hbGV8ZmVtYWxlKSIpW1sxXV0KICAgIHJldHVybihtYXBfZGYocGVvcGxlLCB+IG11dGF0ZShyb3dfZGF0YSwgdmljdGltcyA9IC54KSkpCiAgfQogIAogICMgQ2FzZSAyOiB2YWd1ZSB3aXRoIG51bWJlcgogIG51bWJlcl9tYXRjaCA8LSBzdHJfbWF0Y2godmljdGltX3N0cmluZywgIihcXGQrKXwoW1R0XXdvfFtUdF1ocmVlfFtGZl1vdXJ8W0ZmXWl2ZXxbU3NdaXh8W1NzXWV2ZW58W0VlXWlnaHQpIikKICBpZiAoIWlzLm5hKG51bWJlcl9tYXRjaFsxXSkpIHsKICAgIG51bSA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMobnVtYmVyX21hdGNoWzFdKSkKICAgIGlmIChpcy5uYShudW0pKSB7CiAgICAgIG51bSA8LSBjYXNlX3doZW4oCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0d28iLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDIsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0aHJlZSIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gMywKICAgICAgICBzdHJfZGV0ZWN0KG51bWJlcl9tYXRjaFsxXSwgcmVnZXgoImZvdXIiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDQsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJmaXZlIiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiA1LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgic2l4IiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiA2LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgic2V2ZW4iLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDcsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJlaWdodCIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gOCwKICAgICAgICBzdHJfZGV0ZWN0KG51bWJlcl9tYXRjaFsxXSwgcmVnZXgoImVpZ2h0IiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiA5LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDEwLAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDExLAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDEyLAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDEzLAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDE0LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWlnaHQiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDE1LAogICAgICAgIFRSVUUgfiAxCiAgICAgICkKICAgIH0KICAgIHJldHVybihtYXBfZGYoMTpudW0sIH4gbXV0YXRlKHJvd19kYXRhLCB2aWN0aW1zID0gIlVua25vd24iKSkpCiAgfQogIAogICMgRGVmYXVsdDogcmV0dXJuIG9yaWdpbmFsIHJvdwogIHJldHVybihyb3dfZGF0YSkKfQoKIyBBcHBseSB0byBlYWNoIHJvdwpjbGVhbmVkX2RmIDwtIGRmICU+JQogIHJvd3dpc2UoKSAlPiUKICBkbyhleHBhbmRfdmljdGltcyguJHZpY3RpbXMsIC4pKSAlPiUKICB1bmdyb3VwKCkKCiMgRmlyc3QgZXh0cmFjdCB0aGUgY291bnRyeQpjbGVhbmVkX2RmIDwtIGNsZWFuZWRfZGYgJT4lCiAgbXV0YXRlKGNvdW50cnkgPSBzdHJfZXh0cmFjdChsb2NhdGlvbiwgIlteLF0rJCIpICU+JSBzdHJfdHJpbSgpKQoKIyBUaGVuIHJlbW92ZSBhbnkgdHJhaWxpbmcgcGVyaW9kcwpjbGVhbmVkX2RmIDwtIGNsZWFuZWRfZGYgJT4lCiAgbXV0YXRlKGNvdW50cnkgPSBzdHJfcmVtb3ZlKGNvdW50cnksICJcXC4kIikpCgpjbGVhbmVkX2RmICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb3VudHJ5LCBmaWxsID0gdHlwZV9vZl9hdHRhY2spKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyAgCiAgbGFicyh0aXRsZSA9ICJBdHRhY2tzIGFuZCBDb3VudHJ5IiwKICAgICAgIHggPSAiQ291bnRyeSIsCiAgICAgICB5ID0gIkNvdW50IG9mIEF0dGFja3MiKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICAKCgpgYGAKCmBgYHtyLCBvdXQud2lkdGg9IjEwMCUiLCBvdXQuaGVpZ2h0PSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm1lZGlhL1NlY29uZF9BdHRlbXB0LnBuZyIpCmBgYAoKCiMgKipDbGVhbmVyIFdvbGYgRGF0YSoqCgpgYGB7ciwgZWNobz1UUlVFfQojIExvYWQgYW5kIGNsZWFuIHRoZSBkYXRhc2V0CmRmIDwtIHJlYWRfY3N2KCJwcmVkYXRvcnMvZ2xvYmFsX3dvbHZlcy5jc3YiKSAlPiUgCiAgY2xlYW5fbmFtZXMoKQoKIyBGdW5jdGlvbiB0byBleHBhbmQgdmljdGltcyBhbmQgZXh0cmFjdCBhZ2UgJiBzZXgKZXhwYW5kX3ZpY3RpbXMgPC0gZnVuY3Rpb24odmljdGltX3N0cmluZywgcm93X2RhdGEpIHsKICByb3dfZGF0YSA8LSBhc190aWJibGUocm93X2RhdGEpICAKICAKICB2aWN0aW1fc3RyaW5nIDwtIHN0cl9yZXBsYWNlX2FsbCh2aWN0aW1fc3RyaW5nLCAiKG1hbGV8ZmVtYWxlKSg/PVtBLVpdKSIsICJcXDE7ICIpCgogIGlmIChzdHJfZGV0ZWN0KHZpY3RpbV9zdHJpbmcsICJbQS1aYS16XSssPyA/XFxkezEsMn0sIChtYWxlfGZlbWFsZSkiKSkgewogICAgcGVvcGxlIDwtIHN0cl9leHRyYWN0X2FsbCh2aWN0aW1fc3RyaW5nLCAiW14sO10rLD8gP1xcZHsxLDJ9LCAobWFsZXxmZW1hbGUpIilbWzFdXQogICAgCiAgICByZXR1cm4obWFwX2RmKHBlb3BsZSwgZnVuY3Rpb24ocGVyc29uKSB7CiAgICAgIGFnZSA8LSBzdHJfZXh0cmFjdChwZXJzb24sICJcXGR7MSwyfSIpICU+JSBhcy5udW1lcmljKCkKICAgICAgc2V4IDwtIHN0cl9leHRyYWN0KHBlcnNvbiwgIm1hbGV8ZmVtYWxlIikKICAgICAgbXV0YXRlKHJvd19kYXRhLCB2aWN0aW1zID0gcGVyc29uLCBhZ2UgPSBhZ2UsIHNleCA9IHNleCkKICAgIH0pKQogIH0KCiAgbnVtYmVyX21hdGNoIDwtIHN0cl9tYXRjaCh2aWN0aW1fc3RyaW5nLCAiKFxcZCspfChbVHRdd298W1R0XWhyZWV8W0ZmXW91cnxbRmZdaXZlfFtTc11peHxbU3NdZXZlbnxbRWVdaWdodHxbTm5daW5lfFtUdF1lbnxbRWVdbGV2ZW58W1R0XXdlbHZlfFtUdF1oaXJ0ZWVufFtGZl1vdXJ0ZWVufFtGZl1pZnRlZW4pIikKICAKICBpZiAoIWlzLm5hKG51bWJlcl9tYXRjaFsxXSkpIHsKICAgIG51bSA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMobnVtYmVyX21hdGNoWzFdKSkKICAgIGlmIChpcy5uYShudW0pKSB7CiAgICAgIG51bSA8LSBjYXNlX3doZW4oCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0d28iLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDIsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0aHJlZSIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gMywKICAgICAgICBzdHJfZGV0ZWN0KG51bWJlcl9tYXRjaFsxXSwgcmVnZXgoImZvdXIiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDQsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJmaXZlIiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiA1LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgic2l4IiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiA2LAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgic2V2ZW4iLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDcsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJlaWdodCIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gOCwKICAgICAgICBzdHJfZGV0ZWN0KG51bWJlcl9tYXRjaFsxXSwgcmVnZXgoIm5pbmUiLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDksCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0ZW4iLCBpZ25vcmVfY2FzZSA9IFRSVUUpKSB+IDEwLAogICAgICAgIHN0cl9kZXRlY3QobnVtYmVyX21hdGNoWzFdLCByZWdleCgiZWxldmVuIiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiAxMSwKICAgICAgICBzdHJfZGV0ZWN0KG51bWJlcl9tYXRjaFsxXSwgcmVnZXgoInR3ZWx2ZSIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gMTIsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJ0aGlydGVlbiIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gMTMsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJmb3VydGVlbiIsIGlnbm9yZV9jYXNlID0gVFJVRSkpIH4gMTQsCiAgICAgICAgc3RyX2RldGVjdChudW1iZXJfbWF0Y2hbMV0sIHJlZ2V4KCJmaWZ0ZWVuIiwgaWdub3JlX2Nhc2UgPSBUUlVFKSkgfiAxNSwKICAgICAgICBUUlVFIH4gMQogICAgICApCiAgICB9CiAgICAKICAgIHJldHVybihtYXBfZGYoMTpudW0sIH4gbXV0YXRlKHJvd19kYXRhLCB2aWN0aW1zID0gIlVua25vd24iLCBhZ2UgPSBOQSwgc2V4ID0gTkEpKSkKICB9CgogIHNleCA8LSBzdHJfZXh0cmFjdCh2aWN0aW1fc3RyaW5nLCAibWFsZXxmZW1hbGUiKQogIGFnZSA8LSBzdHJfZXh0cmFjdCh2aWN0aW1fc3RyaW5nLCAiXFxkezEsMn0iKSAlPiUgYXMubnVtZXJpYygpCiAgCiAgcmV0dXJuKG11dGF0ZShyb3dfZGF0YSwgdmljdGltcyA9IHZpY3RpbV9zdHJpbmcsIGFnZSA9IGFnZSwgc2V4ID0gc2V4KSkKfQoKIyBFeHBhbmQgdmljdGltcyBpbnRvIGluZGl2aWR1YWwgcm93cwpjbGVhbmVkX2RmIDwtIGRmICU+JQogIHJvd3dpc2UoKSAlPiUKICBkbyhleHBhbmRfdmljdGltcyguJHZpY3RpbXMsIC4pKSAlPiUKICB1bmdyb3VwKCkKCiMgQ2xlYW4gY291bnRyeSBpbmZvIGZyb20gJ2xvY2F0aW9uJyBjb2x1bW4KY2xlYW5lZF9kZiA8LSBjbGVhbmVkX2RmICU+JQogIG11dGF0ZSgKICAgIGNvdW50cnkgPSBzdHJfZXh0cmFjdChsb2NhdGlvbiwgIlteLF0rJCIpICU+JSBzdHJfdHJpbSgpLAogICAgY291bnRyeSA9IHN0cl9yZW1vdmUoY291bnRyeSwgIlxcLiIpCiAgKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGNvdW50cnkpICYgY291bnRyeSAhPSAiIikKCiMgR2V0IHRvcCAxNSBjb3VudHJpZXMgYnkgbnVtYmVyIG9mIGF0dGFja3MKdG9wX2NvdW50cmllcyA8LSBjbGVhbmVkX2RmICU+JQogIGNvdW50KGNvdW50cnksIHNvcnQgPSBUUlVFKSAlPiUKICBzbGljZV9oZWFkKG4gPSAxNSkgJT4lCiAgcHVsbChjb3VudHJ5KQoKIyBGaWx0ZXIgdG8ganVzdCB0aG9zZSBjb3VudHJpZXMKZmlsdGVyZWRfZGYgPC0gY2xlYW5lZF9kZiAlPiUKICBmaWx0ZXIoY291bnRyeSAlaW4lIHRvcF9jb3VudHJpZXMpCgpmaWx0ZXJlZF9kZiA8LSBmaWx0ZXJlZF9kZiAlPiUKICBmaWx0ZXIoIWlzLm5hKHR5cGVfb2ZfYXR0YWNrKSAmIHR5cGVfb2ZfYXR0YWNrICE9ICIiKQoKIyBQbG90CmZpbHRlcmVkX2RmICU+JQogIGdncGxvdChhZXMoeCA9IGZjdF9pbmZyZXEoY291bnRyeSksIGZpbGwgPSB0eXBlX29mX2F0dGFjaykpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAxNSBDb3VudHJpZXMgd2l0aCBXb2xmIEF0dGFja3MiLAogICAgeCA9ICJDb3VudHJ5IiwKICAgIHkgPSAiTnVtYmVyIG9mIEF0dGFja3MiLAogICAgZmlsbCA9ICJBdHRhY2sgVHlwZSIKICApICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxOCksCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApCgpgYGAKCgoKQWZ0ZXIgY2xlYW5pbmcgdGhlIGRhdGEsIHlvdSBjYW4gc2VlLCBSdXNzaWEgYW5kIEZyYW5jZSBib3RoIGhhdmUgbWFueSBhdHRhY2tzLgoKCiMgKipXaG8gaXMgS2luZz8qKgoKYGBge3IsIGVjaG89VFJVRX0KCiMgMS4gU3VtbWFyaXplIHRoZSBudW1iZXIgb2YgYXR0YWNrcyBmcm9tIGVhY2ggY2xlYW5lZCBkYXRhc2V0CgojIEFsbGlnYXRvcgpnYXRvcl9hdHRhY2tzIDwtIGdhdG9yICU+JQogIGZpbHRlcighaXMubmEoZGF0ZSkpICU+JQogIG5yb3coKQoKIyBTaGFyayAtIFVzaW5nIHNoYXJrXzEgc2luY2UgaXQgaGFzIG1vc3Qgcm93cyBhbmQgd2FzIHByZS1jbGVhbmVkCnNoYXJrX2F0dGFja3MgPC0gc2hhcmtfMSAlPiUKICBmaWx0ZXIoIWlzLm5hKHR5cGUpLCB0eXBlICE9ICJVbmtub3duIikgJT4lCiAgbnJvdygpCgojIFdvbHZlcyAtIFVzaW5nIGNsZWFuZWRfZGYgZnJvbSB3b2xmIGRhdGEKd29sZl9hdHRhY2tzIDwtIGNsZWFuZWRfZGYgJT4lCiAgZmlsdGVyKCFpcy5uYSh0eXBlX29mX2F0dGFjayksIHR5cGVfb2ZfYXR0YWNrICE9ICIiKSAlPiUKICBucm93KCkKCiMgMi4gQ3JlYXRlIGEgY29tcGFyaXNvbiBkYXRhIGZyYW1lCmF0dGFja19raW5nX2RmIDwtIHRpYmJsZSgKICBwcmVkYXRvciA9IGMoIlNoYXJrIiwgIkFsbGlnYXRvciIsICJXb2xmIiksCiAgdG90YWxfYXR0YWNrcyA9IGMoc2hhcmtfYXR0YWNrcywgZ2F0b3JfYXR0YWNrcywgd29sZl9hdHRhY2tzKQopCgojIDMuIFBsb3QgaXQKYXR0YWNrX2tpbmdfZGYgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihwcmVkYXRvciwgdG90YWxfYXR0YWNrcyksIHkgPSB0b3RhbF9hdHRhY2tzLCBmaWxsID0gcHJlZGF0b3IpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjYpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdG90YWxfYXR0YWNrcyksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVGhlIEtpbmcgb2YgQXR0YWNrcyIsCiAgICB4ID0gIlByZWRhdG9yIiwKICAgIHkgPSAiRG9jdW1lbnRlZCBBdHRhY2tzIgogICkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlNoYXJrIiA9ICIjRkYzQzM4IiwgIkFsbGlnYXRvciIgPSAiIzBDOTQ2MyIsICJXb2xmIiA9ICIjNEM0QzZEIikpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE2KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMjApLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgKQoKYGBgCgoKCgojICoqTG9uZyBMaXZlIEtpbmcgSmF3cyoqCgpUaGUgS2luZyBvZiBhdHRhY2tzIGlzIHRoZSBzaGFyay4gVGhlIGRhdGEgc2hvd3MgdGhhdCBzaGFya3MgaGF2ZSB0aGUgbW9zdCBhdHRhY2tzLiBMb29rIGF0IHRoZSBtYXAgb2YgQXVzdHJhbGlhIGFnYWluLCBldmVyeSBtYXJrZXIgaXMgd2hlcmUgYSBzaGFyayBhdHRhY2sgaGFzIG9jY3VycmVkLiBBbHNvLCBhbm90aGVyIHJlYXNvbiB3aHkgdGhlIHNoYXJrIGRhdGEgaXMga2luZyBpcyBkdWUgdG8gYSBsYWNrIGFuZCBtaXNzaW5nIGRhdGEgZnJvbSBib3RoIHRoZSB3b2x2ZXMgYW5kIGdhdG9ycy4gSWYgdGhlcmUgd2FzIGRhdGEgZm9yIE5pbGUgQ3JvY3MsIHRoZXJlIG1pZ2h0IGJlIHNvbWUgY29tcGV0aXRpb24uIAoKCmBgYHtyLCBvdXQud2lkdGg9IjcwJSIsIG91dC5oZWlnaHQ9IjcwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJtZWRpYS9zaGFyay5wbmciKQpgYGAKClBpY3R1cmUgZnJvbSBbYnJpdGFubmljYV0oaHR0cHM6Ly93d3cuYnJpdGFubmljYS5jb20vYW5pbWFsL3NoYXJrKQoKCiMgKipUb3VyIEd1aWRlIFRpcHMqKgoKV2hlbiB2aXNpdGluZyBGbG9yaWRhIG9yIEF1c3RyYWxpYSwgd2F0Y2ggeW91ciBmZWV0IGFuZCBzdXJyb3VuZGluZ3MuIEluIEZsb3JpZGEsIHByZXR0eSBtdWNoIGV2ZXJ5dGhpbmcgd2FudHMgdG8gZWF0IHlvdSBmcm9tIGJ1Z3MgdG8gQWxsaWdhdG9ycy9Dcm9jcywgc25ha2VzLCBzaGFya3MsIGV0Yy4gSXQgaXMgYSBkYW5nZXJvdXMgYW5kIHdvbmRlcmZ1bCBwbGFjZSwgYXMgbG9uZyBhcywgeW91IGFyZSBjYXJlZnVsLiBCZXNpZGVzLCBhbGwgdGhlIHRoaW5ncyB0aGF0IGFyZSB3YW50aW5nIHRvIGVhdCB5b3UuLi5tYWtlIGZvciBhIHRhc3R5IG1lYWwgb24geW91ciBkaW5uZXIgcGxhdGUgaW4gdGhlIGVuZC4gSSB3YW50IHRvIHJldHVybiB0byBGbG9yaWRhIHRvIGdldCBzb21lIGNyb2MvZ2F0b3IgbWVhdC4gU2hhcmsgaXMgbm90IGJhZCwgaXQgaXMganVzdCBhIGZpc2h5LCBjaGV3eSBtZWF0LiAKCkF1c3RyYWxpYSBoYXMgYSBsYXJnZXIgdmFyaWV0eSBvZiBkYW5nZXJzLCBhIGxvdCBvZiBzaGFyayBhdHRhY2tzLCBwb2lzb25vdXMgc25ha2VzLCBqZWxseWZpc2gsIGNyb2NzLCBhbmQgb3RoZXIgZGFuZ2Vycy4gUEJTIGhhcyBiZWVuIG15IGd1aWRlIHRvIEF1c3RyYWxpYS4gCgojICoqTWFpbiBQb2ludHM6KioKCjEtIERvIG5vdCB1bmRlcmVzdGltYXRlIGEgcHJlZGF0b3IgYnkgdGhpbmtpbmcgdGhleSBhcmUgc2xvdwoKMi0gV2F0Y2ggeW91ciBzdXJyb3VuZGluZ3MKCjMtIEJlIGNhcmVmdWwgd2hlbiBnb2luZyBuZWFyIGFueSB3YXRlciBzb3VyY2UKCjQtIERvbid0IHByb3Zva2UgdGhlIHdpbGRsaWZlCgo1LSBEbyBub3QgZmVlZCB0aGUgd2lsZGxpZmUKCjYtIERvIG5vdCBnZXQgY2xvc2UgdG8gdGhlIHdpbGRsaWZlIChQb3RlbnRpYWwgRGVhdGggUmlzaykKCjctIElmIHlvdSBhcmUgc3R1bmcgYnkgYSBqZWxseWZpc2ggcmluc2UgdGhlIGFyZWEgd2l0aCB3YXRlciwgZG8gbm90IHVyaW5hdGUgb24gaXQKCjgtIElmIHlvdSBhcmUgYml0LCAoZGVwZW5kaW5nIG9uIHdoYXQgYml0IHlvdSBhbmQgd2hlcmUgeW91IGFyZSBiaXQpIGlmIHlvdSBoYXZlIGEgd2VhcG9uLCBmaWdodCBiYWNrLiAKCldpdGggY3JvY3MgYW5kIGdhdG9yczogZXllcywgbm9zZSwgb3IgdGhyb2F0IGFyZSByZWNvbW1lbmRlZCB0byBzdGFiIGF0LiBJZiBpdCBpcyBhIHNuYWtlIG9yIGEgaW5zZWN0IGdldCBoZWxwLCBhcyBzb29uIGFzIHBvc3NpYmxlLiAKCklmIHlvdSBhcmUgYml0IGJ5IGEgZ2F0b3IvY3JvYywgc2hhcmssIHNuYWtlcywgYW50cywgc3BpZGVycywgb3IgYW55IHNvcnQgb2Ygd2lsZGxpZmUgZ2V0IGhlbHAgQVNBUCwgeW91IGNhbiBwb3RlbnRpYWxseSBkaWUgZnJvbSBhIGJhY3RlcmlhbCBpbmZlY3Rpb24gb3IgcmFiaWVzLiAKClNvbWUgc25ha2VzIGluIEZsb3JpZGEgKGNvdHRvbm1vdXRoIHNuYWtlKSBhcmUganVzdCBuYXN0eSBhbmQgaGF2ZSBhIGJhZCBiYWN0ZXJpYSBpbiB0aGVpciBtb3V0aCB0aGF0IHdpbGwgY2F1c2UgZ2FuZ3JlbmUuIAoKCiMgKipIb25vcmFibGUgTWVudGlvbnMqKgoKMS0gR29sZGVuIExhYnMKCjItIEJpcmRzCgozLSBKZWxseWZpc2gKCjQtIEV0Yy4g